#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>


#define LED2_ON    0X10
#define LED2_OFF   0X20
#define LED3_ON    0X30
#define LED3_OFF   0X40

#define BUZZER_ON  0x50  
#define BUZZER_OFF 0x60



//LED2
#define GPX2CON 0x11000c40
#define GPX2DAT 0x11000c44

void __iomem *gpx2con_vir;
void __iomem *gpx2dat_vir;


//LED3
#define GPX1CON 0x11000c20
#define GPX1DAT 0x11000c24


void __iomem *gpx1con_vir;
void __iomem *gpx1dat_vir;



//BUZZER
#define  GPD0CON  0x114000A0

#define  TCFG0    0x139D0000
#define  TCFG1	  0x139D0004
#define  TCNTB0	  0x139D000c
#define  TCMPB0	  0x139D0010
#define  TCON	  0x139D0008

void __iomem *gpd0con_vir;
void __iomem *tcfg0_vir;
void __iomem *tcfg1_vir;
void __iomem *tcntb0_vir;
void __iomem *tcmpb0_vir;
void __iomem *tcon_vir;
	



unsigned int major = 0;
struct class *cls;
struct device *dev;

struct mutex my_mutex;

int flag = 1;
int led_open(struct inode *node, struct file *filp)
{

	printk("-----%s----\n",__FUNCTION__);
	mutex_lock(&my_mutex);
	flag--;
	if(flag < 0){
            printk("device is busy!\n");
			flag++;
            return -1;
       }
	return 0;

}

int led_close(struct inode *node, struct file *filp)
{
	printk("-----%s----\n",__FUNCTION__);
		flag++;
	mutex_unlock(&my_mutex);
	return 0;
}


long led_ioctl(struct file *filp, unsigned int cmd , unsigned long args)
{

	printk("cmd:%d",cmd);
	switch(cmd)
	{
		case LED2_ON:
			writel(readl(gpx2dat_vir)|(0X1 << 7),gpx2dat_vir);
			break;
		case LED2_OFF:
			writel(readl(gpx2dat_vir)&~(0x1 << 7),gpx2dat_vir);
			break;
		case LED3_ON:
			writel(readl(gpx1dat_vir)|0x1,gpx1dat_vir);
			break;
		case LED3_OFF:
			writel(readl(gpx1dat_vir)&~0x1,gpx1dat_vir);
			break;
		case BUZZER_ON:
			writel(0x9,tcon_vir);	
			break;
		case BUZZER_OFF:
			writel(0xa,tcon_vir);
			break;
		default:
			break;
	}
	return 0;


}

struct file_operations fops = {
	.open = led_open,
	.release = led_close,
	.unlocked_ioctl = led_ioctl,
};


static int led_init(void)
{
	printk("-----%s----\n",__FUNCTION__);
	major = register_chrdev(0,"majdev",&fops);
	if(major < 0)
	{
		printk("fail to register");
		return -1;
	}

	cls = class_create(THIS_MODULE,"led");
	device_create(cls,NULL,MKDEV(major,0),NULL,"led2");

	mutex_init(&my_mutex);


	//LED_INIT
	
	gpx2con_vir = ioremap(GPX2CON,4);
	gpx2dat_vir = ioremap(GPX2DAT,4);
	gpx1con_vir = ioremap(GPX1CON,4);
	gpx1dat_vir = ioremap(GPX1DAT,4);
	writel((readl(gpx2con_vir)& ~(0xf<<28))|(0x1<<28),gpx2con_vir);
	writel((readl(gpx1con_vir)& ~0xf)|0x1,gpx1con_vir);

	//BUZZER_INIT
	gpd0con_vir = ioremap(GPD0CON,4);
	tcfg0_vir = ioremap(TCFG0,4);
	tcfg1_vir = ioremap(TCFG1,4);
	tcntb0_vir = ioremap(TCNTB0,4);
	tcmpb0_vir = ioremap(TCMPB0,4);
	tcon_vir = ioremap(TCON,4);
	
	writel((readl(gpd0con_vir)& ~0xf)|0x2,gpd0con_vir);	
	writel(450,tcfg0_vir);
	writel(8,tcfg1_vir);
	writel(500,tcntb0_vir);
	writel(250,tcmpb0_vir);
	

	return 0;
}

static void led_exit(void)
{
	printk("-----%s----\n",__FUNCTION__);
	device_destroy(cls,MKDEV(major,0));
	class_destroy(cls);
	
	unregister_chrdev(major,"majdev");
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("Dual BSD/GPL");


